from .consts.common import JIAZI
from .consts import shensha_consts


class ShenSha:
    """
    神煞：只使用get_item返回指定的对象
    """
    _cache = {}
    _inited = False

    def __new__(cls, name, no):
        if cls._inited:
            raise RuntimeError(f'{cls.__name__} 已经加载，不能直接实例化，请使用 {cls.__name__}.get_item(name)')
        if name in cls._cache:
            return cls._cache[name]
        else:
            self = super().__new__(cls)
            cls._cache[name] = self
            return self

    def __init__(self, name, no):
        self.name = name
        self.no = no  # 编号

    @classmethod
    def check_lushen(cls, mingpan):
        """
        检查禄神
        """
        riyuan = mingpan.riyuan.gan.name
        ans = [[], [], [], []]
        for i, zhu in enumerate(mingpan.sizhu):
            zhi = zhu[1].zhi.name
            if [riyuan, zhi] in shensha_consts.LUSHEN:
                ans[i].append(cls.get_item('禄神'))
        return ans

    @classmethod
    def check_yangren(cls, mingpan):
        """
        检查羊刃
        """
        riyuan = mingpan.riyuan.gan.name
        ans = [[], [], [], []]
        for i, zhu in enumerate(mingpan.sizhu):
            zhi = zhu[1].zhi.name
            if [riyuan, zhi] in shensha_consts.YANGREN:
                ans[i].append(cls.get_item('羊刃'))
        return ans

    @classmethod
    def check_yima(cls, mingpan):
        zhis = [zhu[1].zhi.name for zhu in mingpan.sizhu]
        nian_zhi, ri_zhi = zhis[0], zhis[2]
        ans = [[], [], [], []]
        for i, zhi in enumerate(zhis):
            cond1 = [nian_zhi, zhi] in shensha_consts.YIMA
            cond2 = [ri_zhi, zhi] in shensha_consts.YIMA
            if cond1 or cond2:
                ans[i].append(cls.get_item('驿马'))
        return ans

    @classmethod
    def check_taohua(cls, mingpan):
        zhis = [zhu[1].zhi.name for zhu in mingpan.sizhu]
        nian_zhi, ri_zhi = zhis[0], zhis[2]
        ans = [[], [], [], []]
        for i, zhi in enumerate(zhis):
            cond1 = [nian_zhi, zhi] in shensha_consts.TAOHUA
            cond2 = [ri_zhi, zhi] in shensha_consts.TAOHUA
            if cond1 or cond2:
                ans[i].append(cls.get_item('桃花'))
        return ans

    @classmethod
    def check_huagai(cls, mingpan):
        zhis = [zhu[1].zhi.name for zhu in mingpan.sizhu]
        nian_zhi, ri_zhi = zhis[0], zhis[2]
        ans = [[], [], [], []]
        for i, zhi in enumerate(zhis):
            cond1 = [nian_zhi, zhi] in shensha_consts.HUAGAI if i != 0 else False
            cond2 = [ri_zhi, zhi] in shensha_consts.HUAGAI if i != 2 else False
            if cond1 or cond2:
                ans[i].append(cls.get_item('华盖'))
        return ans

    @classmethod
    def check_kuigang(cls, mingpan):
        ri_zhu = mingpan.sizhu[2]
        gz = ri_zhu[0].gan.name + ri_zhu[1].zhi.name
        ans = [[], [], [], []]
        if gz in shensha_consts.KUIGANG:
            ans[2].append(cls.get_item('魁罡'))
        return ans

    @classmethod
    def check_kongwang(cls, mingpan):
        """
        检查空亡, 空亡又叫六甲空亡
        """
        sizhu = mingpan.sizhu
        nian_zhu = sizhu[0][0].gan.name + sizhu[0][1].zhi.name
        ri_zhu = sizhu[2][0].gan.name + sizhu[2][1].zhi.name
        # 年柱和日支所在的甲子旬
        nian_xun = JIAZI[(JIAZI.index(nian_zhu) // 10) * 10]
        ri_xun = JIAZI[(JIAZI.index(ri_zhu) // 10) * 10]

        ans = [[], [], [], []]
        for i, zhu in enumerate(sizhu):
            zhi = zhu[1].zhi.name
            cond1 = zhi in shensha_consts.KONGWANG[nian_xun]
            cond2 = zhi in shensha_consts.KONGWANG[ri_xun]
            if cond1 or cond2:
                ans[i].append(cls.get_item('空亡'))
        return ans

    @classmethod
    def check_ycyc(cls, mingpan):
        ri_zhu = mingpan.sizhu[2]
        gz = ri_zhu[0].gan.name + ri_zhu[1].zhi.name
        ans = [[], [], [], []]
        if gz in shensha_consts.YCYC:
            ans[2].append(cls.get_item('阴差阳错'))
        return ans

    @classmethod
    def check_muku(cls, mingpan):
        gans = [zhu[0].gan.name for zhu in mingpan.sizhu]
        zhis = [zhu[1].zhi.name for zhu in mingpan.sizhu]
        ans = [[], [], [], []]
        for i, zhi in enumerate(zhis):
            for gan in gans:
                if [gan, zhi] in shensha_consts.MUKU:
                    ans[i].append(cls.get_item('墓库'))
                    break
        return ans

    @classmethod
    def check_tjgr(cls, mingpan):
        nian_gan = mingpan.sizhu[0][0].gan.name
        ri_gan = mingpan.sizhu[2][0].gan.name
        zhis = [zhu[1].zhi.name for zhu in mingpan.sizhu]
        tjgr_cbs = []
        for x, ys in shensha_consts.TAIJIGUIREN:
            for y in ys:
                tjgr_cbs.append([x, y])
        ans = [[], [], [], []]
        for i, zhi in enumerate(zhis):
            if [nian_gan, zhi] in tjgr_cbs or [ri_gan, zhi] in tjgr_cbs:
                ans[i].append(cls.get_item('太极贵人'))
        return ans

    @classmethod
    def check_tygr(cls, mingpan):
        nian_gan = mingpan.sizhu[0][0].gan.name
        ri_gan = mingpan.sizhu[2][0].gan.name
        zhis = [zhu[1].zhi.name for zhu in mingpan.sizhu]
        tygr_cbs = []
        for x, ys in shensha_consts.TIANYIGUIREN:
            for y in ys:
                tygr_cbs.append([x, y])
        ans = [[], [], [], []]
        for i, zhi in enumerate(zhis):
            if [nian_gan, zhi] in tygr_cbs or [ri_gan, zhi] in tygr_cbs:
                ans[i].append(cls.get_item('天乙贵人'))
        return ans

    @classmethod
    def check_tcgr(cls, mingpan):
        nian_gan = mingpan.sizhu[0][0].gan.name
        ri_gan = mingpan.sizhu[2][0].gan.name
        zhis = [zhu[1].zhi.name for zhu in mingpan.sizhu]
        tcgr_cbs = shensha_consts.TIANCHUGUIREN
        ans = [[], [], [], []]
        for i, zhi in enumerate(zhis):
            if [nian_gan, zhi] in tcgr_cbs or [ri_gan, zhi] in tcgr_cbs:
                ans[i].append(cls.get_item('天厨贵人'))
        return ans

    @classmethod
    def check_gygr(cls, mingpan):
        nian_gan = mingpan.sizhu[0][0].gan.name
        ri_gan = mingpan.sizhu[2][0].gan.name
        zhis = [zhu[1].zhi.name for zhu in mingpan.sizhu]
        gygr_cbs = shensha_consts.GUOYINGUIREN
        ans = [[], [], [], []]
        for i, zhi in enumerate(zhis):
            if [nian_gan, zhi] in gygr_cbs or [ri_gan, zhi] in gygr_cbs:
                ans[i].append(cls.get_item('国印贵人'))
        return ans

    @classmethod
    def check_ydgr(cls, mingpan):
        yueling = mingpan.yueling.zhi.name
        gans = [zhu[0].gan.name for zhu in mingpan.sizhu]
        ydgr_cbs = []
        for zs, g in shensha_consts.YUEDEGUIREN:
            for z in zs:
                ydgr_cbs.append([g, z])
        ans = [[], [], [], []]
        for i, gan in enumerate(gans):
            if [gan, yueling] in ydgr_cbs:
                ans[i].append(cls.get_item('月德贵人'))
        return ans

    @classmethod
    def check_tdgr(cls, mingpan):
        yueling = mingpan.yueling.zhi.name
        ans = [[], [], [], []]
        for i, zhu in enumerate(mingpan.sizhu):
            gan = zhu[0].gan.name
            zhi = zhu[1].zhi.name
            if [yueling, gan] in shensha_consts.TIANDEGUIREN or [yueling, zhi] in shensha_consts.TIANDEGUIREN:
                ans[i].append(cls.get_item('天德贵人'))
        return ans

    @classmethod
    def check_sqgr(cls, mingpan):
        gans = [zhu[0].gan.name for zhu in mingpan.sizhu]
        x = ''.join(gans[0:3])
        y = ''.join(gans[1:4])
        ans = [[], [], [], []]
        if x in shensha_consts.SANQIGUIREN:
            ans[2].append(cls.get_item('三奇贵人'))
        if y in shensha_consts.SANQIGUIREN:
            ans[3].append(cls.get_item('三奇贵人'))
        return ans

    @classmethod
    def check_tggr(cls, mingpan):
        nian_gan = mingpan.sizhu[0][0].gan.name
        ri_gan = mingpan.sizhu[2][0].gan.name
        zhis = [zhu[1].zhi.name for zhu in mingpan.sizhu]
        tggr_cbs = shensha_consts.TIANGUANGUIREN
        ans = [[], [], [], []]
        for i, zhi in enumerate(zhis):
            if [nian_gan, zhi] in tggr_cbs or [ri_gan, zhi] in tggr_cbs:
                ans[i].append(cls.get_item('天官贵人'))
        return ans

    @classmethod
    def check_wcgr(cls, mingpan):
        nian_gan = mingpan.sizhu[0][0].gan.name
        ri_gan = mingpan.sizhu[2][0].gan.name
        zhis = [zhu[1].zhi.name for zhu in mingpan.sizhu]
        tggr_cbs = shensha_consts.WENCHANGGUIREN
        ans = [[], [], [], []]
        for i, zhi in enumerate(zhis):
            if [nian_gan, zhi] in tggr_cbs or [ri_gan, zhi] in tggr_cbs:
                ans[i].append(cls.get_item('文昌贵人'))
        return ans

    @classmethod
    def check_jiangxing(cls, mingpan):
        zhis = [zhu[1].zhi.name for zhu in mingpan.sizhu]
        nian_zhi, ri_zhi = zhis[0], zhis[2]
        ans = [[], [], [], []]
        for i, zhi in enumerate(zhis):
            cond1 = [nian_zhi, zhi] in shensha_consts.JIANGXING if i != 0 else False
            cond2 = [ri_zhi, zhi] in shensha_consts.JIANGXING if i != 2 else False
            if cond1 or cond2:
                ans[i].append(cls.get_item('将星'))
        return ans

    @classmethod
    def check_hongluan(cls, mingpan):
        zhis = [zhu[1].zhi.name for zhu in mingpan.sizhu]
        pivot = zhis[0]
        ans = [[], [], [], []]
        for i, zhi in enumerate(zhis):
            if [pivot, zhi] in shensha_consts.HONGLUAN:
                ans[i].append(cls.get_item('红鸾'))
        return ans

    @classmethod
    def check_jinyu(cls, mingpan):
        zhis = [zhu[1].zhi.name for zhu in mingpan.sizhu]
        riyuan = mingpan.riyuan.gan.name
        ans = [[], [], [], []]
        for i, zhi in enumerate(zhis):
            if [riyuan, zhi] in shensha_consts.JINYU:
                ans[i].append(cls.get_item('金舆'))
        return ans


    @classmethod
    def check_yuanchen(cls, mingpan):
        zhis = [zhu[1].zhi.name for zhu in mingpan.sizhu]
        pivot = zhis[0]
        ans = [[], [], [], []]
        cond1 = mingpan.is_male()
        cond2 = mingpan.sizhu[0][0].gan.yinyang.is_yang()
        if cond1 == cond2:
            table = shensha_consts.YUANCHEN[0]
        else:
            table = shensha_consts.YUANCHEN[1]
        for i, zhi in enumerate(zhis):
            if [pivot, zhi] in table:
                ans[i].append(cls.get_item('元辰'))
        return ans

    @classmethod
    def check_ciguan(cls, mingpan):
        zhus = [zhu[0].gan.name + zhu[1].zhi.name for zhu in mingpan.sizhu]
        riyuan = mingpan.riyuan.gan.name
        ans = [[], [], [], []]
        for i, zhu in enumerate(zhus):
            if [riyuan, zhu] in shensha_consts.CIGUAN:
                ans[i].append(cls.get_item('词馆'))
        return ans

    @classmethod
    def check_sedb(cls, mingpan):
        rizhu = mingpan.sizhu[2][0].gan.name + mingpan.sizhu[2][1].zhi.name
        ans = [[], [], [], []]
        if rizhu in shensha_consts.SHIEDABAI:
            ans[2].append(cls.get_item('十恶大败'))
        return ans

    @classmethod
    def check_gls(cls, mingpan):
        rizhu = mingpan.sizhu[2][0].gan.name + mingpan.sizhu[2][1].zhi.name
        ans = [[], [], [], []]
        if rizhu in shensha_consts.GULUANSHA:
            ans[2].append(cls.get_item('孤鸾煞'))
        return ans

    @classmethod
    def check_zaisha(cls, mingpan):
        zhis = [zhu[1].zhi.name for zhu in mingpan.sizhu]
        pivot = zhis[0]
        ans = [[], [], [], []]
        for i, zhi in enumerate(zhis):
            if [pivot, zhi] in shensha_consts.ZAISHA:
                ans[i].append(cls.get_item('灾煞'))
        return ans

    @classmethod
    def init_shensha(cls, items):
        """
        加载支持的神煞，初始化的时候调用一次
        """
        for no, name in items:
            cls(name, no)
        cls._inited = True

    @classmethod
    def get_item(cls, name):
        """
        返回指定的对象
        """
        return cls._cache[name]

    def __str__(self):
        return self.name

    def __repr__(self):
        return f"{self.__class__.__name__}('{self.name}', {self.no})"
